﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wizard.Source;

namespace Wizard.MsSql
{
    public class DataStore : Wizard.IDataStore
    {
        
        public DataStore()
        {
        }


        #region IDataStore Members

        IDataStoreContext IDataStore.GetNewContext()
        {
            return new DataStoreContext();
        }

        #endregion

        #region IPlugin Members

        string Wizard.Runtime.IPlugin.FriendlyName
        {
            get { throw new NotImplementedException(); }
        }

        void Wizard.Runtime.IPlugin.Load()
        {
            throw new NotImplementedException();
        }

        void Wizard.Runtime.IPlugin.Initialize(IWizardEngine engine)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class DataStoreContext : Wizard.IDataStoreContext
    {
        private Entities mEntities;

        internal DataStoreContext()
        {
            mEntities = new Entities();
        }

        IWizardApplication Wizard.IDataStoreContext.NewApplication(string applicationName)
        {
            var result = new Application();
            result.ApplicationName = applicationName;
            mEntities.AddToApplications(result);
            InternalSaveChanges();
            return result;
        }

        private void InternalSaveChanges()
        {
            mEntities.SaveChanges(true);
        }

        ISession Wizard.IDataStoreContext.GetSession(string sessionKey)
        {
            Session session;
            var sessions = (from sess in mEntities.Sessions where sess.SessionKey == sessionKey select sess);
            if (sessions.Count() > 0)
            {
                session = sessions.First();
            }
            else
            {
                session = new Session();
                session.SessionKey = sessionKey;
                session.Created = DateTime.Now;
                mEntities.AddToSessions(session);
                InternalSaveChanges();
            }
            return session;
        }

        void Wizard.IDataStoreContext.DeleteApplication(IWizardApplication application)
        {
            DeleteObject(application);
        }

        public void DeleteObjects(System.ComponentModel.IListSource list)
        {
            DeleteObjects(list.GetList());
        }

        public void DeleteObjects(System.Collections.IList list)
        {
            var len = list.Count;
            var objects = new object[len];
            list.CopyTo(objects, 0);
            for (int i = 0; i < len; i++)
            {
                DeleteObject(objects[i]);
            }
        }

        public void DeleteObject(object o)
        {
            if (o == null) return;
            var owner = o as IOwnObjects;
            if (owner != null)
            {
                owner.DeleteOwnedObjects(this);
            }
            mEntities.DeleteObject(o);
        }

        void Wizard.IDataStoreContext.ClearDatabase()
        {
            DeleteObjects(mEntities.Applications);
            DeleteObjects(mEntities.ClassInstances);
            DeleteObjects(mEntities.ClassMembers);
            DeleteObjects(mEntities.ClassSources);
            DeleteObjects(mEntities.FunctionSources);
            DeleteObjects(mEntities.LocalVariableSources);
            DeleteObjects(mEntities.MethodInstances);
            DeleteObjects(mEntities.MethodParameters);
            DeleteObjects(mEntities.MethodSources);
            DeleteObjects(mEntities.Sessions);
            DeleteObjects(mEntities.StatementParameterSources);
            DeleteObjects(mEntities.StatementSources);
            DeleteObjects(mEntities.TransitionSources);
            InternalSaveChanges();
        }

        ISession[] Wizard.IDataStoreContext.GetSessions()
        {
            var result=(ISession[])mEntities.Sessions.ToArray();
            return result;
        }


        void Wizard.IDataStoreContext.DeleteSession(int sessionId)
        {
            var session = (from Session e in mEntities.Sessions where e.SessionId == sessionId select e).First();
            mEntities.DeleteObject(session);
            InternalSaveChanges();
        }

        IWizardApplication[] Wizard.IDataStoreContext.GetApplications()
        {
            var result = (IWizardApplication[])mEntities.Applications.ToArray();
            return result;
        }

        void Wizard.IDataStoreContext.DeleteApplication(int applicationId)
        {
            var application = (from Application a in mEntities.Applications where a.ApplicationId == applicationId select a).First();
            mEntities.DeleteObject(application);
            InternalSaveChanges();
        }

        IWizardApplication Wizard.IDataStoreContext.GetApplication(int applicationId)
        {
            var app = (from Application a in mEntities.Applications where a.ApplicationId == applicationId select a).First();
            return app;            
        }


        ISourceFile Wizard.IDataStoreContext.GetSourceFile(int sourceFileId)
        {
            var result = (from SourceFile s in mEntities.SourceFiles where s.SourceFileId == sourceFileId select s).First();
            return result;
        }

        Wizard.Source.ISourceFile[] Wizard.IDataStoreContext.GetSourceFiles(int applicationId)
        {
            var result = from SourceFile s in mEntities.SourceFiles where s.Application.ApplicationId == applicationId select s;
            return result.ToArray();
        }

        public void DeleteSourceFile(int sourceFileId)
        {
            var result = (from SourceFile s in mEntities.SourceFiles where s.SourceFileId == sourceFileId select s).First();
            mEntities.DeleteObject(result);
            InternalSaveChanges();
        }

//            mEntities.DeleteObject(application.c);

        void IDataStoreContext.DeleteSourceFile(int sourceFileId)
        {
            throw new NotImplementedException();
        }

        void IDataStoreContext.DeleteClassSources(IWizardApplication application)
        {
            //mEntities.DeleteObject(classes);
        }

        IClassSource[] IDataStoreContext.GetClasses(int queryApplicationId)
        {
            var result = from ClassSource s in mEntities.ClassSources where s.Application.ApplicationId == queryApplicationId select s;
            return result.ToArray();
        }


        void IDataStoreContext.SaveAllChanges()
        {
            InternalSaveChanges();
        }
    }
}
